package cn.bluedot.framework.util;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

public class BeanUtil {

	/**
	 * 通用map转Bean对象
	 * @param params
	 * @param cls
	 * @return
	 */
	public static <T> T toBean(Map<String, ?> params, Class<T> cls) {
		
		try {
			T bean = cls.newInstance();
			BeanUtils.populate(bean, params);
			return bean;
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
		
	/**
	 * 结果集转map,适用于单条记录
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	private static Map<String, Object> resultSetToMap(ResultSet rs) throws Exception {
		
		Map<String, Object> map = new HashMap<>();
		
		ResultSetMetaData metaData = rs.getMetaData();
		
		List<String> list = metaDataToList(metaData); //列名驼峰
		
		if(rs.next()) {
						
			for (int i = 0; i < list.size(); i++) {
				map.put(list.get(i), rs.getObject(i+1));
			}		
		}
		
		return map;
	}
	
	/**
	 * 结果集转list,适用于多条记录
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	private static List<Map<String, Object>> resultSetToListMap(ResultSet rs) throws Exception {
		
		List<Map<String, Object>> listMap = new ArrayList<>();
		
		ResultSetMetaData metaData = rs.getMetaData();
		
		List<String> list = metaDataToList(metaData); //列名驼峰
		
		while(rs.next()) {
			
			Map<String, Object> map = new HashMap<>();
			
			for (int i = 0; i < list.size(); i++) {
				map.put(list.get(i), rs.getObject(i+1));
			}
			
			listMap.add(map);			
		}
		
		return listMap;
	}
	
	/**
	 * 结果集转bean对象
	 * @param rs
	 * @param cls
	 * @return
	 * @throws Exception
	 */
	public static <T> T toBean(ResultSet rs, Class<T> cls) throws Exception {
		
		Map<String, Object> params = resultSetToMap(rs);
		
		return toBean(params, cls);
	}

	/**
	 * 结果集转List对象
	 * @param rs
	 * @param cls
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> toBeanList(ResultSet rs, Class<T> cls) throws Exception {
		List<T> list = new ArrayList<>();
		List<Map<String, Object>> listMap = resultSetToListMap(rs);
		
		for (int i = 0; i < listMap.size(); i++) {
			Map<String, Object> params = listMap.get(i);
			T bean = toBean(params, cls);
			list.add(bean);
		}
		
		return list;
	}
	
	/**
	 * map转List对象
	 * @param rs
	 * @param cls
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> toBeanList(List<Map<String, Object>> listMap, Class<T> cls) throws Exception {
		List<T> list = new ArrayList<>();
		
		for (int i = 0; i < listMap.size(); i++) {
			Map<String, Object> params = listMap.get(i);
			T bean = toBean(params, cls);
			list.add(bean);
		}
		
		return list;
	}

	
	/**
	 * 将列名转为驼峰
	 * @param metaData
	 * @return
	 * @throws SQLException
	 */
	private static List<String> metaDataToList(ResultSetMetaData metaData) throws SQLException {
		int count = metaData.getColumnCount();
		
		if(count == 0) {
			return null;
		}
		
		List<String> list = new ArrayList<String>(count);
		
		for (int i = 0; i < count; i++) {
			String columnName = metaData.getColumnName(i+1);
			String column = underlineToCamel(columnName);
			list.add(i, column);
		}
				
		return list;
	}
	
	
	
	/**
	 * 封装结果集
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	public static List<Map<String,Object>> getListHashMap(ResultSet rs) throws Exception{
		List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
		
		HashMap<String,Object> hashMap = null;
		ResultSetMetaData metaData = rs.getMetaData();
		int columnCount = metaData.getColumnCount(); //得到字段数
		
		while(rs.next()){  
            hashMap=new HashMap<String, Object>();  
            for(int i = 0;i<columnCount;i++){              	
            	String label = metaData.getColumnLabel(i+1); //列名
            	label = underlineToCamel(label); //下划线转驼峰
            	
                hashMap.put(label,rs.getObject(i+1));  
            }  
            list.add(hashMap);  
        }  
		
		return list;
	}
	
	
	/**
	 * 驼峰转下划线
	 * @param param 需要转换的字符串
	 * @param charType 转换类型：2全部大写，其他全部小写
	 * @return
	 */
    public static String camelToUnderline(String param, Integer charType) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < param.length(); i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append("_");
            }
            if (charType == 2) {
                sb.append(Character.toUpperCase(c));  //统一都转大写
            } else {
                sb.append(Character.toLowerCase(c));  //统一都转小写
            }

        }
        return sb.toString();
    }

    /**
     * 下划线转驼峰
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        Boolean flag = false; // "_" 后转大写标志,默认字符前面没有"_"
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == '_') {
                flag = true;
                continue;   //标志设置为true,跳过
            } else {
                if (flag == true) {
                    //表示当前字符前面是"_" ,当前字符转大写
                    sb.append(Character.toUpperCase(param.charAt(i)));
                    flag = false;  //重置标识
                } else {
                    sb.append(Character.toLowerCase(param.charAt(i)));
                }
            }
        }
        return sb.toString();
    }	
	
}
